https://habr.com/ru/articles/813781/ источник
Каждый запущенный экземпляр постгри обслуживает одну или несколько баз данных.
Каталог, в котором размещаются все файлы, относящиеся к кластеру, обычно называют словом PGDATA, по имени переменной окружения, указывающей на этот каталог.
При инициализации в PGDATA создаются три одинаковые базы данных:
template0
используется, например, для восстановления из логической резервной копии или для создания базы в другой кодировке и никогда недолжна меняться;template1
служит шаблоном для всех остальных баз данных, которые может создать пользователь в этом кластере;postgres
представляет собой обычную базу данных, которую можно использовать по своему усмотрению.Для выполнения команды CREATE DATABASE
необходимо подключение к серверу базы данных. Первая база данных всегда создаётся командой initdb
при инициализации пространства хранения данных (см. документацию.) Эта база данных называется postgres
.
База данных postgres
используется пользователями и приложениями для подключения по умолчанию. Представляет собой всего лишь копию template1
, и может быть удалена и повторно создана.
template1
является примером для создания остальных баз, поэтому при изменении её, изменения будут касаться остальных созданных баз.
template0
нужна когда нужно создат базу с дефолтными значениями,тк она неизменяема и такая же как начальнео состояние template0
По факту команда CREATE DATABASE
выполняет копирование существующей базы данных. По умолчанию копируется стандартная системная база template1
.
CREATE DATABASE users TEMPLATE template0;
Если в команде CREATE DATABASE
указать в качестве шаблона template0
вместо template1
, вы сможете получить «чистую» пользовательскую базу данных (в которой никаких пользовательских объектов нет, есть только системные объекты в первозданном виде), не содержащую ничего, что могло быть добавлено на месте в template1
(Рис. 1.3)
Системные каталоги начинаются с приставки pg_ и хранят метаднные в частности информацию о таблицах и столбцах, а также служебные сведения. Сами по себе это обычные таблицы и к ним моно обращаться через обычные запросы, например pg_database
В отличие от большинства системных каталогов, pg_database
разделяется всеми базами данных кластера: есть только один экземпляр pg_database
в кластере, а не отдельные в каждой базе данных.
Схема представляет из себя некое пространство имен для сущностей внутри БД
То есть, нельзя дублировать нзвания таблиц или функций итд только в рамках схемы.
По дефолту все создается и ищется в схеме public, но схем может быть больше
Также существует схема pg_catalog где храняся все системные сущности и по умолчанию поиск начинается с этой схемы.
Дефолтный порядок поиска объектов:
Табличные пространства определяют физическое расположение данных. Фактически табличное пространство — это каталог файловой системы.
При инициализации кластера создаются два табличных пространства:
pg_default
располагается в каталоге PGDATA/base
и используется как табличное пространство по умолчанию, если явно не выбрать для этой цели другое пространство;pg_global
располагается в каталоге PGDATA/global
и хранит общие для всего кластера объекты системного каталога.Для создания табличного пространства используется команда CREATE TABLESPACE, например::
CREATE TABLESPACE fastspace LOCATION '/ssd1/postgresql/data';
Табличные пространства могут быть использованы например чтобы хранить что то редко-используемое на медленных носителях, а часто используемомоое на быстрых
Создадим индекс по столбцу в табличном пространстве fastspace
:
CREATE INDEX code_idx ON films (code) TABLESPACE fastspace;
Разные БД могу хранить данные в разных табличных пространствах.
Внутри каталога PGDATA
(На убунте это /var/lib/postgresql/12/main) есть подкаталог base. Этот
каталог и есть табличное пространство base.
Для каждой базы данных в кластере существует подкаталог внутри PGDATA/base
(Если только я не создал БД в отдельном табличном пространстве), названный по OID базы данных в pg_database
. Этот подкаталог по умолчанию является местом хранения файлов базы данных; в частности, там хранятся её системные каталоги
Если перейти в директорию конкретной базы, то там будет много много файлов.
Каждая таблица и индекс хранятся в отдельном файле. Для обычных отношений, эти файлы получают имя по номеру файлового узла таблицы или индекса, который содержится в pg_class
.relfilenode
Если relfilenode
больше нуля, то файл найти можно, если равно нулю, то либо временное, либо не протоколируемое итд
Где именно хранятся данные для таких таблиц где relfilenode
=0 зависит от режима работы PostgreSQL и конфигурации базы данных.
Помимо главного файла (также называемого основным слоем), у каждой таблицы и индекса есть карта свободного пространства (документация). Но появляется она не сразу, а только при необходимости. Имя файла карты свободного пространства образуется из номера файлового узла с суффиксом _fsm
.
Также таблицы имеют карту видимости, хранящуюся в слое с суффиксом _vm
, она существует для таблиц, но не для индексов (документация)
Когда объём таблицы или индекса превышает 1 GB, они делятся на сегменты размером в один гигабайт (Рис. 1.19). Файл первого сегмента называется по номеру файлового узла (filenode
); последующие сегменты получают имена filenode.1
, filenode.2
и т. д.
Каждое пользовательское табличное пространство имеет символическую ссылку внутри каталога PGDATA/pg_tblspc
.
Ссылка ведет на адрес этого пространства. Каждое пользовательское табличное пространство имеет символическую ссылку внутри каталога PGDATA/pg_tblspc
. Внутри физической папки табличного пространства, табличное пространство лежит в папке PG_16_202307071, это есть название версии хоста. Это нужно чтобы разные версии постгри могли использовать одно и то же местоположение, заданное в CREATE TABLESPACE
.
Функция pg_relation_filepath()
показывает полный путь (относительно PGDATA
) для любого отношения.
SELECT pg_relation_filepath('db1.public.new1');
Существует несколько слоев. Слой это файл. Для удобства организации ввода-вывода файлы логически поделены на страницы (или блоки) — это минимальный объем данных, который считывается или записывается.
main fork
) — это собственно данные: те самые табличные или индексные строки. Данные разделены на страницы.init fork
) существует только для не журналируемых таблиц (созданных с указанием UNLOGGED) и их индексов. Такие объекты ничем не отличаются от обычных, кроме того, что действия с ними не записываются в журнал предзаписи. За счет этого работа с ними происходит быстрее, но в случае сбоя невозможно восстановить данные в согласованном состоянии. Поэтому при восстановлении PostgreSQL просто удаляет все слои таких объектов и записывает слой инициализации на место основного слоя. В результате получается «пустышка».free space map
) — слой, в котором отслеживается примерный объем свободного места внутри страниц.visibility map
) — слой, который позволяет быстро определить, требует ли страница очистки или заморозки. Для каждой страницы хранит два бита, требует ли страница заморзки или страница является видимой.TOAST (The Oversized-Attribute Storage Technique, Методика хранения сверхбольших атрибутов).
PostgreSQL использует фиксированный размер страницы (обычно 8 КБ), и не позволяет строчке таблицы занимать несколько страниц.
TOAST подразумевает несколько сценариев действий.
Если какие-либо столбцы таблицы хранятся в формате TOAST, у таблицы будет связанная с ней таблица TOAST, OID которой хранится в значении pg_class
.reltoastrelid
Код обработки TOAST распознаёт четыре различные стратегии хранения столбцов, совместимых с TOAST, на диске:
PLAIN
не допускает ни сжатия, ни отдельного хранения. Это единственно возможная стратегия для столбцов типов данных, которые несовместимы с TOAST.EXTENDED
допускает как сжатие, так и отдельное хранение. Это стандартный вариант для большинства типов данных, совместимых с TOAST. Сначала происходит попытка выполнить сжатие, затем — сохранение вне таблицы, если строка всё ещё слишком велика.EXTERNAL
допускает отдельное хранение, но не сжатие. Использование EXTERNAL
ускорит операции над частями строк в больших столбцах text
и bytea
(ценой увеличения объёма памяти для хранения), так как эти операции оптимизированы для извлечения только требуемых частей отделённого значения, когда оно не сжато.MAIN
допускает сжатие, но не отдельное хранение. (Фактически для таких столбцов будет тем не менее применяться отдельное хранение, но лишь как крайняя мера, когда нет другого способа уменьшить строку так, чтобы она помещалась на странице.)